from fastapi import FastAPI, Request, Response
from settings.development import settings
from starlette.middleware.cors import CORSMiddleware
from router.router import api_v1_router
from common.logger import logger
from common import custom_exc


def create_app() -> FastAPI:
    """
    生成FatAPI对象
    :return:
    """
    app = FastAPI(
        debug=settings.DEBUG,
        title=settings.TITLE,
        description=settings.DESCRIPTION,
        docs_url=settings.DOCS_URL,
        openapi_url=settings.OPENAPI_URL,
        redoc_url=settings.REDOC_URL
    )

    # 跨域设置
    register_cors(app)

    # 注册路由
    register_router(app)

    # 注册捕获全局异常
    # register_exception(app)

    # # 请求拦截
    # register_hook(app)

    # # 取消挂载在 request对象上面的操作，感觉特别麻烦，直接使用全局的
    # register_init(app)

    # if settings.DEBUG:
    #     # 注册静态文件
    #     register_static_file(app)

    return app


def register_cors(app: FastAPI) -> None:
    """
    支持跨域
    :param app:
    :return:
    """
    if settings.DEBUG:
        app.add_middleware(
            CORSMiddleware,
            allow_origins=["*"],
            allow_credentials=True,
            allow_methods=["*"],
            allow_headers=["*"],
        )

def register_router(app: FastAPI) -> None:
    """
    注册路由
    :param app:
    :return:
    """
    # 项目API
    app.include_router(
        api_v1_router,
    )

# def register_exception(app: FastAPI) -> None:
#     """
#     全局异常捕获
#     注意 别手误多敲一个s
#     exception_handler
#     exception_handlers
#     两者有区别
#         如果只捕获一个异常 启动会报错
#         @exception_handlers(UserNotFound)
#     TypeError: 'dict' object is not callable
#     :param app:
#     :return:
#     """

#     # 自定义异常 捕获
#     @app.exception_handler(custom_exc.TokenExpired)
#     async def user_not_found_exception_handler(request: Request, exc: custom_exc.TokenExpired):
#         """
#         token过期
#         :param request:
#         :param exc:
#         :return:
#         """
#         logger.error(
#             f"token未知用户\nURL:{request.method}{request.url}\nHeaders:{request.headers}\n{traceback.format_exc()}")

#         return response_code.resp_4002(message=exc.err_desc)

#     @app.exception_handler(custom_exc.TokenAuthError)
#     async def user_token_exception_handler(request: Request, exc: custom_exc.TokenAuthError):
#         """
#         用户token异常
#         :param request:
#         :param exc:
#         :return:
#         """
#         logger.error(f"用户认证异常\nURL:{request.method}{request.url}\nHeaders:{request.headers}\n{traceback.format_exc()}")

#         return response_code.resp_4003(message=exc.err_desc)

#     @app.exception_handler(custom_exc.AuthenticationError)
#     async def user_not_found_exception_handler(request: Request, exc: custom_exc.AuthenticationError):
#         """
#         用户权限不足
#         :param request:
#         :param exc:
#         :return:
#         """
#         logger.error(f"用户权限不足 \nURL:{request.method}{request.url}")
#         return response_code.resp_4003(message=exc.err_desc)

#     @app.exception_handler(ValidationError)
#     async def inner_validation_exception_handler(request: Request, exc: ValidationError):
#         """
#         内部参数验证异常
#         :param request:
#         :param exc:
#         :return:
#         """
#         logger.error(
#             f"内部参数验证错误\nURL:{request.method}{request.url}\nHeaders:{request.headers}\n{traceback.format_exc()}")
#         return response_code.resp_5002(message=exc.errors())

#     @app.exception_handler(RequestValidationError)
#     async def request_validation_exception_handler(request: Request, exc: RequestValidationError):
#         """
#         请求参数验证异常
#         :param request:
#         :param exc:
#         :return:
#         """
#         logger.error(
#             f"请求参数格式错误\nURL:{request.method}{request.url}\nHeaders:{request.headers}\n{traceback.format_exc()}")
#         # return response_code.resp_4001(message='; '.join([f"{e['loc'][1]}: {e['msg']}" for e in exc.errors()]))
#         return response_code.resp_4001(message=exc.errors())

#     # 捕获全部异常
#     @app.exception_handler(Exception)
#     async def all_exception_handler(request: Request, exc: Exception):
#         """
#         全局所有异常
#         :param request:
#         :param exc:
#         :return:
#         """
#         logger.error(f"全局异常\n{request.method}URL:{request.url}\nHeaders:{request.headers}\n{traceback.format_exc()}")
#         return response_code.resp_500()